#include <iostream>
using std::cout;
using std::endl;

void print(int x){
    cout << "print:" << x << endl;
}

void display(int x){
    cout << "display:" << x << endl;
}

class FFF{
public:
    void print(int x){
        cout << "FFF::print:" << x << endl;
    }

    void display(int x){
        cout << "FFF::display:" << x << endl;
    }
};

class DDD{
public:
    void print(int x){
        cout << "FFF::print:" << x << endl;
    }

    void display(int x){
        cout << "FFF::display:" << x << endl;
    }
};


//将此类的函数指针的类型定名为Func
typedef void (*Func)(int);
//将此类的成员函数指针的类型定名为MemberFunc
typedef void (FFF::*MemberFunc)(int);

void test1(){
    Func p = print;
    p(6);

    p = display;
    p(7);
}

void test3(){
    //创建成员函数指针的时候就已经确定了
    //返回类型、参数、是哪个类的成员函数
    MemberFunc p = &FFF::print;
    FFF fff;
    //成员指针访问运算符的第一种形式
    //指针指的是p，这是一个成员函数指针
    (fff.*p)(10);

    p = &FFF::display;
    /* p = &DDD::print; */

    FFF * pff = new FFF();
    //成员指针访问运算符的第二种形式
    (pff->*p)(11);

    pff = nullptr;
    (pff->*p)(11);


}

void test2(){
    /* void (FFF::*p)(int) = &FFF::print; */
    //FFF::print这个写法显示出print是FFF类的成员函数
    //前面加上&是完整的写法
    //成员函数指针的定义和使用不能用省略的写法
    //定义成员函数指针的时候也需要加上类作用域
    void (FFF::*p)(int) = &FFF::print;
    FFF fff;

    //先获取成员函数，再进行调用
    //.*是成员指针访问运算符，这里的指针指的是p
    (fff.*p)(6);

    p = &FFF::display;
    (fff.*p)(7);

    /* void (FFF::*p2)(int) = &FFF::print; */
}


void test0(){
    //定义函数指针时就已经确定了
    //这个函数指针只能指向特定类型的函数
    //返回类型、参数类型都确定了
    //省略形式
    void (*p)(int) = print;
    p(4);

    p = display;
    p(5);

    //完整形式
    void (*p2)(int) = &print;
    (*p2)(6);

    /* p = show;//error,参数不一致 */
    /* p(); */

    /* p = down; */
}

int main(void){
    test3();
    return 0;
}
